package com.feinno.urcs.group.service;

import com.feinno.sip.message.Content;
import com.feinno.superpojo.SuperPojoManager;
import com.feinno.urcs.content.MimeType;
import com.feinno.urcs.content.UrcsMultipartMimeContent;
import com.feinno.urcs.dns.EnumService;
import com.feinno.urcs.group.GroupConfiguration;
import com.feinno.urcs.group.GroupError;
import com.feinno.urcs.group.GroupException;
import com.feinno.urcs.group.api.*;
import com.feinno.urcs.group.entity.*;
import com.feinno.urcs.group.interop.entity.FetionFileMessageArgs;
import com.feinno.urcs.group.interop.entity.FetionGroupArgs;
import com.feinno.urcs.group.interop.entity.FetionTextMessageArgs;
import com.feinno.urcs.group.interop.service.util.FetionMessageType;
import com.feinno.urcs.group.log.*;
import com.feinno.urcs.group.pctask.task.AndPcGroupMsgArgs;
import com.feinno.urcs.group.siptask.task.GroupFileTransferArgs;
import com.feinno.urcs.group.siptask.task.GroupMessageArgs;
import com.feinno.urcs.group.siptask.task.GroupSmsArgs;
import com.feinno.urcs.group.siptask.task.GroupTaskEvents;
import com.feinno.urcs.group.util.DateUtils;
import com.feinno.urcs.group.util.MSRPTextMsgParser;
import com.feinno.urcs.group.util.MsrpContent;
import com.feinno.urcs.profile.UserSessionService;
import com.feinno.urcs.profile.entity.ClientType;
import com.feinno.urcs.profile.entity.PcCapacity;
import com.feinno.urcs.sipservlet.SipServletRequest;
import com.feinno.urcs.types.MobileNo;
import com.feinno.util.StringUtils;
import org.helium.framework.annotations.ServiceImplementation;
import org.helium.framework.annotations.ServiceSetter;
import org.helium.framework.annotations.TaskEvent;
import org.helium.framework.task.TaskProducer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.sip.address.SipURI;
import java.io.IOException;
import java.util.Date;
import java.util.List;

/**
 * Created by Lei Gao on 5/12/15.
 */
@ServiceImplementation
public class GroupChatServiceImpl implements GroupChatService {
	private static final Logger LOGGER = LoggerFactory.getLogger(GroupChatServiceImpl.class);
	@ServiceSetter
	private GroupService groupService;
	@ServiceSetter
	private GroupTerminalService groupTerminalService;
	@ServiceSetter
	private EnumService enumService;
	@ServiceSetter
	private GroupActiveService groupAcitveService;
	@ServiceSetter
	private GroupMessageStorageService groupMessageStorageService;
	@ServiceSetter
	private UserSessionService userSessionService;
	@ServiceSetter
	private SmsQuotaService smsQuotaService;
	@TaskEvent(GroupTaskEvents.GROUP_SESSION_MODE_MESSAGE)
	private TaskProducer<GroupMessageArgs> messageTask;
	@TaskEvent(GroupTaskEvents.GROUP_FILE_TRANSFER)
	private TaskProducer<GroupFileTransferArgs> fileTransferTask;
	@TaskEvent(GroupTaskEvents.GROUP_FETION_MESSAGE_TEXT)
	private TaskProducer<FetionTextMessageArgs> fetionSendTextTask;
	@TaskEvent(GroupTaskEvents.GROUP_FETION_MESSAGE_FILE)
	private TaskProducer<FetionFileMessageArgs> fetionSendFileTask;
	@TaskEvent(GroupTaskEvents.GROUP_MESSAGE_TO_PC)
	private TaskProducer<AndPcGroupMsgArgs> andPcGroupMsgTask;
	@TaskEvent(GroupTaskEvents.GROUP_SMS)
	private TaskProducer<GroupSmsArgs> sendSmsTask;
	@ServiceSetter
	private GroupMessageLogService groupMessageLogService;


	/**
	 * send text message
	 * search group member
	 */
	@Override
	public void sendText(int groupId, MobileNo memberMobile, String contentType, byte[] content, ClientType clientType, List<MobileNo> groupAtMembers, Date sendTime) throws Exception {
		// 活跃客户端更新
		try {
			userSessionService.setActiveClient(memberMobile, clientType);
		} catch (Exception e) {
			LOGGER.warn(String.format("memberMobile=%s is userSessionService error  ", memberMobile), e);
		}

		GroupMessageArgs args;
		GroupIndex index = groupService.getGroupIndex(groupId);
		GroupInfo info = groupService.getGroupInfo(index);
		List<GroupMember> membersTo = info.getMembers();
		groupAcitveService.acitve(groupId);
		long groupMessageStorageId = groupMessageStorageService.storageTextMessage(groupId, memberMobile, contentType, content, clientType);
		groupMessageLogService.textMessageUpstreamLog(String.valueOf(groupMessageStorageId), memberMobile, info
				, clientType.name(), MessageDirection.UP, MessageContentType.TXT, new String(content), DateUtils.getUTCNow());
		for (GroupMember memberTo : membersTo) {
			LOGGER.info("sendText disPatch GroupText Group={}, Mobile={}", groupId, memberMobile);

			if (61 == memberTo.getIdentity()) {
				continue;
			}
			args = new GroupMessageArgs();
			args.setGroupId(groupId);
			args.setFromMobile(memberMobile);
			args.setToMobile(memberTo.getMobileNo());
			args.setContentType(contentType);
			args.setContent(content);
			args.setDomain(GroupConfiguration.INSTANCE.getGroupDomain());
			args.setConversationId(info.getConversationId());
			args.setGroupMessageStorageId(groupMessageStorageId);
			args.setIsPc(clientType == ClientType.PC);
			args.setSendTime(sendTime);
			if (null != groupAtMembers && groupAtMembers.size() > 0) {
				args.setAtMembers(groupAtMembers);
			}
			SipURI uri = (SipURI) enumService.getSipURI(memberTo.getMobileNo());
			if (uri == null) {
				// 未开通融合通信
				LOGGER.error(String.format("sendText  uri is null  GroupId=%s, MobileNo=%s ", info.getGroupId(), memberTo));
				continue;
			} else {

				groupTerminalService.sendTextMessage(args);
			}
		}
		sendRichTextToFetion(index, memberMobile, content, null);

	}

	@Override
	public void sendFile(int groupId, MobileNo memberMobile, GroupFileInfo groupFileInfo, Date sendTime) throws Exception {
		try {
			groupAcitveService.acitve(groupId);
			// 活跃客户端更新
			ClientType clientType;
			if (groupFileInfo.getIsPc()) {
				clientType = ClientType.PC;
			} else {
				clientType = ClientType.APP;
			}
			try {
				if (clientType != ClientType.PC) {
					userSessionService.removePcCapacity(memberMobile, PcCapacity.IM_CC);
				}
				userSessionService.setActiveClient(memberMobile, clientType);
			} catch (Exception e) {
				LOGGER.warn(String.format("memberMobile=%s is userSessionService error  ", memberMobile), e);
			}
			GroupIndex index = groupService.getGroupIndex(groupId);
			GroupInfo groupInfo = groupService.getGroupInfo(index);
			List<GroupMember> members = groupInfo.getMembers();


			groupMessageLogService.fileMessageUpstreamLog(groupFileInfo.getTransferId(), memberMobile, groupInfo
					, clientType.name(), MessageDirection.UP, groupFileInfo, DateUtils.getUTCNow());

			String senderName = "";
			for (GroupMember member : members) {
				LOGGER.info("dispatch GroupFile Group={}, fromMobile={}, toMobile={}", groupId, memberMobile, member.getMobileNo());
				if (member.getIdentity() == 61) {
					continue;
				}
				if (member.getMobileNo().equals(memberMobile)) {
					senderName = member.getDisplayname();
					if (groupFileInfo.getIsPc()) {
						sendFileToUE(groupId, memberMobile, groupFileInfo, member, sendTime);
					} else {
						sendFileToPC(memberMobile, groupFileInfo, index, groupInfo, senderName, member, sendTime);
					}
				} else {
					sendFileToUE(groupId, memberMobile, groupFileInfo, member, sendTime);
					sendFileToPC(memberMobile, groupFileInfo, index, groupInfo, senderName, member, sendTime);
				}

			}

			sendFileToFetion(index, memberMobile, groupFileInfo);
		} catch (Exception e) {
			LOGGER.error(String.format("sendFile memberMobile=%s groupId=%s is error  ", memberMobile, groupId), e);
		}
	}

	@Override
	public void sendSms(MobileNo sender, int groupId, String content) throws GroupException {
		GroupInfo info = null;
		int sendCount = (int) smsQuotaService.getSendCount(sender);
		if (sendCount >= GroupConfiguration.INSTANCE.getSmsQuotaDay()) {
			throw new GroupException(GroupError.OUOT_OF_QUOTA);
		}
		try {
			info = groupService.getGroupInfo(groupService.getGroupIndex(groupId));
		} catch (Exception e) {
			throw new RuntimeException(e.getMessage());
		}
		MobileNo groupAdmin = info.getGroupAdmin();
		if (!sender.equals(groupAdmin)) {
			throw new GroupException(GroupError.SERVICE_NOT_AUTHORISED);
		}
		smsQuotaService.increase(sender);
		for (GroupMember member : info.getMembers()) {
			LOGGER.info("SendGroupSmsServlet.sendsms, toUser : {}, smsContent: {}", member.getMobileNo().getMobile(), content);
			if (member.getMobileNo().equals(sender)) {
				continue;
			}
			if (member.getIdentity() == 61) {
				continue;
			}
			GroupSmsArgs args = new GroupSmsArgs();
			args.setDestMobileNo(member.getMobileNo());
			args.setText(content + "【此短信发自融合通信】");
			args.setSrcMobileNo(groupAdmin);
			args.setAppId(GroupConfiguration.INSTANCE.getAppId());
			sendSmsTask.produce(args);
		}
	}

	@Override
	public void sendSms(MobileNo sender, int groupId, SipServletRequest request) throws GroupException, IOException {
		sendSms(sender, groupId, getContent(request));
	}

	private void sendFileToPC(MobileNo memberMobile, GroupFileInfo groupFileInfo, GroupIndex index, GroupInfo groupInfo, String senderName, GroupMember member, Date sendTime) {
		try {
			LOGGER.info("sendFileToPC groupFileInfo : {}", groupFileInfo.toJsonObject());
			AndPcGroupMsgArgs andPcGroupRichMsgArgs = new AndPcGroupMsgArgs();
			String fileName = groupFileInfo.getFileName().toLowerCase();
			if (fileName.endsWith("mp4") || fileName.endsWith("avi") || fileName.endsWith("mpeg")) {
				andPcGroupRichMsgArgs.setContentType(GroupMessageType.VIDEO);
				groupFileInfo.setPcMessageType(GroupMessageType.VIDEO);
			} else if (fileName.endsWith("amr") || fileName.endsWith("mp3") || fileName.endsWith("wav")) {
				andPcGroupRichMsgArgs.setContentType(GroupMessageType.AUDIO);
				groupFileInfo.setPcMessageType(GroupMessageType.AUDIO);

			} else if (fileName.endsWith("jpeg") || fileName.endsWith("gif") || fileName.endsWith("bmp") || fileName.endsWith("png") || fileName.endsWith("jpg")) {
				andPcGroupRichMsgArgs.setContentType(GroupMessageType.IMG);
				groupFileInfo.setPcMessageType(GroupMessageType.IMG);
			} else if (fileName.endsWith("vcf")) {
				andPcGroupRichMsgArgs.setContentType(GroupMessageType.CARD);
				groupFileInfo.setPcMessageType(GroupMessageType.CARD);
				andPcGroupRichMsgArgs.setContent(groupFileInfo.getContent());
			} else if (fileName.endsWith("location.xml") || groupFileInfo.getMessageType() == GroupMessageType.LOCATION) {
				andPcGroupRichMsgArgs.setContentType(GroupMessageType.LOCATION);
				groupFileInfo.setPcMessageType(GroupMessageType.LOCATION);
				andPcGroupRichMsgArgs.setContent(groupFileInfo.getContent());
			} else {
				andPcGroupRichMsgArgs.setContentType(GroupMessageType.FILE);
				groupFileInfo.setPcMessageType(GroupMessageType.FILE);
			}
			andPcGroupRichMsgArgs.setFileType(groupFileInfo.getFileType());
			andPcGroupRichMsgArgs.setFileName(groupFileInfo.getFileName());
			andPcGroupRichMsgArgs.setFileSize(groupFileInfo.getFileSize());
			andPcGroupRichMsgArgs.setGroupId(index.getGroupId());
			andPcGroupRichMsgArgs.setSender(memberMobile);
			andPcGroupRichMsgArgs.setSenderName(StringUtils.isNullOrEmpty(senderName) ? memberMobile.getMobile() : senderName);
			andPcGroupRichMsgArgs.setSubject(groupInfo.getSubject());
			andPcGroupRichMsgArgs.setConversationId(groupInfo.getConversationId());
			andPcGroupRichMsgArgs.setToMobile(member.getMobileNo());
			andPcGroupRichMsgArgs.setTimeLen(groupFileInfo.getTimelen());
			if (groupFileInfo.getPcMessageType() == GroupMessageType.IMG ||
					groupFileInfo.getPcMessageType() == GroupMessageType.CARD ||
					groupFileInfo.getPcMessageType() == GroupMessageType.AUDIO ||
					groupFileInfo.getPcMessageType() == GroupMessageType.VIDEO ||
					groupFileInfo.getPcMessageType() == GroupMessageType.FILE ||
					groupFileInfo.getPcMessageType() == GroupMessageType.LOCATION
					) {
				String fileId = groupFileInfo.getTransferId();
				String url = GroupConfiguration.INSTANCE.getHttpDownloadUrl() + fileId;
				andPcGroupRichMsgArgs.setUrl(url);
			}
			andPcGroupRichMsgArgs.setDomain(groupInfo.getDomain());
			andPcGroupRichMsgArgs.setGroupAtMembers(groupFileInfo.getAtMembers());
			andPcGroupRichMsgArgs.setSendTime(sendTime);
			LOGGER.info("sendFileToPC andPcGroupRichMsgArgs : {}", andPcGroupRichMsgArgs.toJsonObject());
			andPcGroupMsgTask.produce(andPcGroupRichMsgArgs);
		} catch (Exception e) {
			LOGGER.warn("andPcGroupMsgTask error", e);
		}
	}

	private void sendFileToUE(int groupId, MobileNo memberMobile, GroupFileInfo groupFileInfo, GroupMember member, Date sendTime) {
		GroupFileTransferArgs args = new GroupFileTransferArgs();
		args.setGroupId(groupId);
		args.setFromMobile(memberMobile);
		args.setToMobile(member.getMobileNo());
		args.setGroupFileInfo(groupFileInfo);
		args.setSendTime(sendTime);
		fileTransferTask.produce(args);
	}


	private void sendFileToFetion(GroupIndex index, MobileNo memberMobile, GroupFileInfo groupFileInfo) {
		try {

			String fxMessageType = FetionMessageType.getFetionMessageFileType(groupFileInfo.getFileName());

			if ("LOCATION".equals(fxMessageType)) {
				LOGGER.info(String.format("sendToFetion LOCATION groupId=%s, member=%s , MessageType=%s", index.getGroupId(), memberMobile, fxMessageType));
				sendRichTextToFetion(index, memberMobile, groupFileInfo.getContent(), fxMessageType);
				return;
			}
			if ("PHONE_CARD".equals(fxMessageType)) {
				LOGGER.info(String.format("sendToFetion PHONE_CARD groupId=%s, member=%s , MessageType=%s", index.getGroupId(), memberMobile, fxMessageType));
				sendRichTextToFetion(index, memberMobile, groupFileInfo.getTransferId().getBytes(), fxMessageType);
				return;
			}


			// TODO 飞信互通，调用飞信FetionGroupService
			FetionFileMessageArgs fetionFileMessageArgs = new FetionFileMessageArgs();
			FetionGroupArgs groupArgs = new FetionGroupArgs();
			groupArgs.setGroupLogicPool(index.getLogicalPool());
			groupArgs.setGroupId(index.getGroupId());
			groupArgs.setOperatorMobileNo(memberMobile);
//			fetionFileMessageArgs.setThumbnail(groupFileInfo.getThumbnail());
			fetionFileMessageArgs.setFileType(FetionMessageType.getFetionMessageFileType(groupFileInfo.getFileName()));
			fetionFileMessageArgs.setContentType(FetionMessageType.getFetionMessageContentType(groupFileInfo.getFileName())); //TODO 需要依据飞信的解析一下
//			fetionFileMessageArgs.setTime(groupFileInfo.getTimelen() / 1000);
			fetionFileMessageArgs.setTime(groupFileInfo.getTimelen());
			fetionFileMessageArgs.setFileName(groupFileInfo.getFileName());
			fetionFileMessageArgs.setFileSize(groupFileInfo.getFileSize());

			fetionFileMessageArgs.setGroup(groupArgs);
			String url = GroupConfiguration.INSTANCE.getHttpDownloadUrl() + groupFileInfo.getTransferId();
			fetionFileMessageArgs.setUrl(url);
			fetionSendFileTask.produce(fetionFileMessageArgs);
		} catch (Exception e) {
			LOGGER.warn("fetionSendFileTask error", e);
			LOGGER.warn(String.format("fetionSendFileTask Group=%s, Mobile=%s ", index.getGroupId(), memberMobile), e);

		}
	}

	public void sendRichTextToFetion(GroupIndex index, MobileNo memberMobile, byte[] content, String objectType) {

		try {

			// TODO 飞信互通，调用飞信FetionGroupService
			FetionTextMessageArgs fetionTextMessageArgs = new FetionTextMessageArgs();
			//TODO  这个contenttype 是得用  msrp消息中的type
			FetionGroupArgs groupArgs = new FetionGroupArgs();
			fetionTextMessageArgs.setContent(content);
			groupArgs.setGroupLogicPool(index.getLogicalPool());
			groupArgs.setGroupId(index.getGroupId());
			groupArgs.setOperatorMobileNo(memberMobile);
			fetionTextMessageArgs.setGroup(groupArgs);
			fetionTextMessageArgs.setObjectType(objectType);
			fetionTextMessageArgs.setContent(content);
			fetionSendTextTask.produce(fetionTextMessageArgs);
		} catch (Exception e) {
			LOGGER.warn(String.format("fetionSendTextTask Group=%s, Mobile=%s ", index.getGroupId(), memberMobile), e);
		}
	}

	/**
	 * parse content from request
	 *
	 * @param request
	 * @return
	 */
	private String getContent(SipServletRequest request) throws IOException {
		UrcsMultipartMimeContent ummc = request.getMultipartMimeContent();
		Content c = ummc.getContent(MimeType.CPIM);
//		Cpim cpim = new Cpim(c.getContent(), Charset.defaultCharset());
		MsrpContent cpim = new MsrpContent(c.getContent());
		String smsContent = "";
		if (cpim.getContentType().equalsIgnoreCase("text/plain")) {
			smsContent = MSRPTextMsgParser.getMsrpMsgContent(cpim);
		} else {
			String xml = MSRPTextMsgParser.getMsrpMsgContent(cpim);
			GroupSmsXmlArgs smsArgs = SuperPojoManager.parseXmlFrom(xml, GroupSmsXmlArgs.class);
			smsContent = smsArgs.getText();
		}
		return smsContent;
	}


}
